package cn.tedu._07springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 日志功能的切面类，用于日志功能增强
 * Aspect:标识此类为切面类，功能增强的类
 */
@Aspect
@Component
public class logAspect {
    //前置通知
    @Before("execution(public int cn.tedu._07springaop.aop.CaculatorImpl.*(..))")
    public void beforeMethod(JoinPoint joinPoint){
        /*
            getSignature():获取签名
            getName():从签名中获取方法名
            getArgs()：获取参数列表
         */
          String methodName =  joinPoint.getSignature().getName();
            String methodArgs =Arrays.toString(joinPoint.getArgs());
        System.out.println("前置通知:开始记录日志...."+ methodName +":"+methodArgs);
    }

    //后置通知：目标方法执行完毕后，执行此方法
    @After("execution(public int cn.tedu._07springaop.aop.CaculatorImpl.*(..))")
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("后置通知：开始记录日志....");
    }


    //返回通知：目标方法return后,执行此方法
    //可以通过returning参数接受目标方法的返回值
    @AfterReturning(value = "execution(public int cn.tedu._07springaop.aop.CaculatorImpl.*(..))",returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint,Object result){
        System.out.println("返回通知：开始记录日志...."+result);
    }

    //异常通知：目标方法异常结束,执行此方法
    //可以获取到异常对象
    @AfterThrowing(value = "execution(public int cn.tedu._07springaop.aop.CaculatorImpl.*(..))",throwing = "ex")
    public void afterReturningMethod(JoinPoint joinPoint,Throwable ex){
        System.out.println("异常通知：开始记录日志....");
    }

    //环绕通知
    @Around(value = "execution(public int cn.tedu._07springaop.aop.CaculatorImpl.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        try{
            System.out.println("环绕通知:目标方法执行之前~~");
            //执行目标方法
           result = joinPoint.proceed();
            System.out.println("环绕通知：目标方法执行之后~~");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕通知:目标方法异常时执行~~");
        }finally {
            System.out.println("环绕通知:目标方法彻底结束之后~~");
        }
        return result;
    }
}
